package com.inderlab.jpin;

import java.util.HashMap;
import java.util.List;
import java.util.ArrayList;
import java.io.*;
import java.util.Iterator;
import java.util.regex.*;

public class JPConfig
{
	HashMap<String, ArrayList>  pins = new HashMap();
	private static boolean compactmode = com.inderlab.jpin.JPAgent.compactmode;
	private static boolean verbosemode = com.inderlab.jpin.JPAgent.verbosemode;
	private static boolean sidemode = com.inderlab.jpin.JPAgent.sidemode;
	
	public JPConfig(String filename)
	{
		LoadConfig(filename);

		if(verbosemode)
		{
			System.out.println((sidemode ? JPColor.MARGIN:"")+JPColor.C5+"[jpin] Config File");
			
			Iterator it = pins.keySet().iterator();
			while(it.hasNext())
			{
				String className = (String)it.next();
				System.out.println((sidemode ? JPColor.MARGIN:"")+JPColor.C5+"  "+className);
			
				List list = (ArrayList)pins.get(className);
				Iterator its = list.iterator();
				while(its.hasNext())
				{
					System.out.println((sidemode ? JPColor.MARGIN:"")+JPColor.C5+"    > "+its.next());											
				}
			}
			System.out.println(JPColor.RESET);
		}
	}
	
	// Check class
	//-------------
	// Format
	//   className:method
	//   className:*
	//   className*:*
	//   *className*:*
	//	 *:*
	public boolean hasClass(String className)
	{		
		if(pins.containsKey("*"))
		{
			return true;			
		}
		else
		{
			Iterator it = pins.keySet().iterator();
			while(it.hasNext())
			{
				String pinClassName = (String)it.next();
				try {
					if(Pattern.matches(pinClassName.replaceAll("\\*",".*"),className))
						return true;
				} catch(Exception e)
				{
					System.out.println("Exception:"+e);
				}
			}
				
			return pins.containsKey(className);			
		}
	}

	// Check method
	public boolean hasMethod(String className, String methodName)
	{
		//System.out.println("["+className+"]["+methodName+"]");
		if(pins.containsKey("*")) 
			return true;
		
		if(hasClass(className))
		{
			try {	
					Iterator it = pins.keySet().iterator();
					while(it.hasNext())
					{
						String pinClassName = (String)it.next();
						try {
							if(Pattern.matches(pinClassName.replaceAll("\\*",".*"),className))
							{
								if(pins.get(pinClassName).contains("*")) 
									return true;													
								else
									return pins.get(pinClassName).contains(methodName);															
							}
						} catch(Exception e)
							{ 
								System.out.println("Exception:"+e); 
							}
					}
			} catch(Exception e)
				{ e.printStackTrace(); }
		}
		
		return false;
	}
	
	// Load Configuartion File
	public void LoadConfig(String filename)
	{
		BufferedReader inConfig = null; 
		File configFile = new File(filename);
		
		// Get File Reader
		try {
			inConfig = new BufferedReader(new FileReader(configFile));			
		} catch(FileNotFoundException ex)
		{
			System.out.println((sidemode ? JPColor.MARGIN:"")+JPColor.C5+"[Config] File Not Found"+JPColor.RESET);			
		}
		
		// Read File
		try {
			try {
				String  line = null;
				String[] ret = null;
				
				while (( line = inConfig.readLine()) != null)
				{
					// System.out.println(JPColor.MARGIN+JPColor.C5+"  [Config] "+line+JPColor.RESET);
					if(line.charAt(0)=='#') continue;
					try {
						ret = ParsePins(line);						
					} catch(Exception e)
					{
						continue;
					}
 
					if(pins.containsKey(ret[0]))
					{
						// Existed Class
						pins.get(ret[0]).add(ret[1]);
					} else {
						// New Class
						ArrayList list = new ArrayList();
						list.add(ret[1]);
						pins.put(ret[0],list);						
					}
				}
			} finally { inConfig.close(); }
		} catch (IOException ex) {
			System.out.println("Error: no config file. Using Default Pin: *:*");
			// add default pin *:*
			ArrayList list = new ArrayList();
			list.add("*");
			pins.put("*",list);			
		}
		
	}
	
	// Format: Class.method
	// --> Class1.method1
	// --> class1.*
	private String[] ParsePins(String text)
	{
		// Split class and method and put into pins hashmap
		return text.split(":");
	}
		
}
